/*******************************************************************************
* Имя файла: chatServer.cpp
* Дата: 01-06-2024
* Разработчик: Андрей Подлегаев
* Группа: 315
* Факультет: ЦДО ТУСУР
* Лицензия: BSD
* Описание: Клиент-серверное приложение (ЦДО ТУСУР)
* *****************************************************************************/

#include "chatServer.h"

/* Реализация функции получения цвета для клиента */
Color getColor(const int& id)
{
  return static_cast<Color>(Color::COLOR_DARK_BLUE + id % Color::COLOR_WHITE);
}

/* Реализация функции установки имени клиента */
void setNameClient(const int& id, char name[])
{
  for(int i = 0; i < clients.size(); ++i) {
      if(clients[i].id==id) {
          clients[i].name=std::string(name);
        }
    }
}

/* Реализация функции вывода сообщений в терминал */
void printMessages(const std::string& str, Color color, const bool endMessages)
{
  std::lock_guard<std::mutex> guard(coutMutex);
  print(str, color);
  if(endMessages) {
      std::cout << '\n';
    }
}

/* Реализация функции отправки широковещательных сообщений */
void broadcastMessage(const std::string& message, const int& idSender)
{
  char tempMessage[MAX_LEN_MESSAGE];
  strcpy(tempMessage, message.c_str());
  for(int i = 0; i < clients.size(); ++i) {
      if(clients[i].id != idSender) {
          send(clients[i].socket, tempMessage, sizeof(tempMessage), 0);
        }
    }
}

/* Реализация функции отправки широковещательных сообщений */
void broadcastMessage(const int& number, const int& idSender)
{
  for(int i{}; i < clients.size(); ++i){
      if(clients[i].id != idSender) {
          send(clients[i].socket, &number, sizeof(number), 0);
        }
    }
}

/* Реализация функции закрытия соединений */
void closeConnection(const int& id)
{
  for(int i{}; i < clients.size(); ++i) {
      if(clients[i].id == id){
          std::lock_guard<std::mutex> guard(clientsMutex);
          clients[i].th.detach();
          clients.erase(clients.begin() + i);
          close(clients[i].socket);
          break;
        }
    }
}

/* Реализация функции обработки клиентских подключений */
void handlerClient(const int& clientSocket, const int& id)
{
  char nameClient[MAX_LEN_USER_NAME];
  char message[MAX_LEN_MESSAGE];
  recv(clientSocket, nameClient, sizeof(nameClient), 0);
  setNameClient(id, nameClient);
  auto colorMassages = getColor(id);

  std::string welcomeMessage = std::string(nameClient) + std::string(" : (присоединился к чату)");
  broadcastMessage("#NULL", id);
  broadcastMessage(id, id);
  broadcastMessage(welcomeMessage, id);

  printMessages(welcomeMessage, colorMassages);

  while(true){
      int bytesReceived = recv(clientSocket, message, sizeof(message), 0);

      if(bytesReceived <= 0) {
          return;
        }

      if(strcmp(message, "#exit") == 0) {
          std::string exitMessage = std::string(nameClient) + std::string(" : (покинул(а) чат)");
          broadcastMessage("#NULL", id);
          broadcastMessage(id, id);
          broadcastMessage(exitMessage, id);

          printMessages(exitMessage, colorMassages);

          closeConnection(id);
          return;
        }

      broadcastMessage(std::string(nameClient), id);
      broadcastMessage(id, id);
      broadcastMessage(std::string(message), id);

      printMessages(std::string(nameClient) + " : ", colorMassages, false);
      printMessages(message);
    }
}
